package rpt.yto.util.beans;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 
 * @author Administrator
 */
public abstract class SuperBean implements Cloneable {

	private String[] names = null;

	public final String[] getAttributeNames() {

		if (names != null)
			return names;

		Class<?> cls = this.getClass();

		Field[] fields = cls.getDeclaredFields();

		names = new String[fields.length];

		for (int i = 0, len = fields.length; i < len; i++) {
			names[i] = fields[i].getName();
		}

		return names;

	}

	public final Object getAttributeValue(String key) throws Exception {
		Class<?> cls = this.getClass();
		Method[] methods = cls.getDeclaredMethods();
		Field[] fields = cls.getDeclaredFields();

		if (key == null)
			throw new Exception("key is not null");

		for (Field field : fields) {

			if (!key.equals(field.getName()))
				continue;

			try {
				String fieldType = field.getType().getSimpleName();
				String fieldGetName = parGetName(field.getName());
				if (!checkGetMet(methods, fieldGetName)) {
					continue;
				}
				Method fieldGetMet = cls
						.getMethod(fieldGetName, new Class[] {});
				Object fieldVal = fieldGetMet.invoke(this, new Object[] {});
				if ("Date".equals(fieldType)) {
					fieldVal = fmtDate((Date) fieldVal);
				}

				return fieldVal;

			} catch (Exception e) {
				continue;
			}

		}

		return null;
	}

	public final void setAttributeValue(String key, Object value) {
		Class<?> cls = this.getClass();
		Method[] methods = cls.getDeclaredMethods();
		Field[] fields = cls.getDeclaredFields();

		for (Field field : fields) {
			if (key.equals(field.getName())) {
				try {

					String fieldSetName = parSetName(field.getName());
					if (!checkSetMet(methods, fieldSetName)) {
						continue;
					}

					Method fieldSetMet = cls.getMethod(fieldSetName,
							field.getType());
					if (null != value && !"".equals(value)) {
						String fieldType = field.getType().getSimpleName();
						if ("String".equals(fieldType)) {
							fieldSetMet.invoke(this , value);

							return;
						} else if ("Date".equals(fieldType)) {
							Date temp = parseDate((String) value);
							fieldSetMet.invoke(this, temp);

							return;
						} else if ("Integer".equals(fieldType)
								|| "int".equals(fieldType)) {
							Integer intval = Integer.parseInt(String
									.valueOf(value));
							fieldSetMet.invoke(this, intval);

							return;
						} else if ("Long".equalsIgnoreCase(fieldType)) {
							Long temp = Long.parseLong((String) value);
							fieldSetMet.invoke(this, temp);

							return;
						} else if ("Double".equalsIgnoreCase(fieldType)) {
							Double temp = Double.parseDouble((String) value);
							fieldSetMet.invoke(this, temp);

							return;
						} else if ("Boolean".equalsIgnoreCase(fieldType)) {
							Boolean temp = Boolean.parseBoolean((String) value);
							fieldSetMet.invoke(this, temp);

							return;
						} else {
							fieldSetMet.invoke(this, value);

							return;
						}
					}

				} catch (Exception e) {
					continue;
				}
			}
		}

	}

	/**
	 * 
	 * @param methods
	 * @param fieldSetMet
	 * @return boolean
	 */
	private boolean checkSetMet(Method[] methods, String fieldSetMet) {
		for (Method met : methods) {
			if (fieldSetMet.equals(met.getName())) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 
	 * @param methods
	 * @param fieldGetMet
	 * @return boolean
	 */
	private boolean checkGetMet(Method[] methods, String fieldGetMet) {
		for (Method met : methods) {
			if (fieldGetMet.equals(met.getName())) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 
	 * @param fieldName
	 * @return String
	 */
	private String parGetName(String fieldName) {
		if (null == fieldName || "".equals(fieldName)) {
			return null;
		}
		return "get" + fieldName.substring(0, 1).toUpperCase()
				+ fieldName.substring(1);
	}

	/**
	 * 
	 * @param fieldName
	 * @return String
	 */
	private String parSetName(String fieldName) {
		if (null == fieldName || "".equals(fieldName)) {
			return null;
		}
		return "set" + fieldName.substring(0, 1).toUpperCase()
				+ fieldName.substring(1);
	}

	/**
	 * 
	 * @param datestr
	 * @return date
	 */
	public static Date parseDate(String datestr) {
		if (null == datestr || "".equals(datestr)) {
			return null;
		}
		try {
			String fmtstr = null;
			if (datestr.indexOf(':') > 0) {
				fmtstr = "yyyy-MM-dd HH:mm:ss";
			} else {

				fmtstr = "yyyy-MM-dd";
			}
			SimpleDateFormat sdf = new SimpleDateFormat(fmtstr, Locale.UK);
			return sdf.parse(datestr);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 
	 * @param date
	 * @return date string
	 */
	public static String fmtDate(Date date) {
		if (null == date) {
			return null;
		}
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
					Locale.US);
			return sdf.format(date);
		} catch (Exception e) {
			return null;
		}
	}

	public String toString() {

		return super.toString();
	}

	public Map<String, Object> getBeanToMap() throws Exception {

		Map<String, Object> beanToMap = new ConcurrentHashMap<String, Object>();

		for (String key : getAttributeNames()) {
			try {
				beanToMap.put(key, getAttributeValue(key));
			} catch (Exception e) {
				continue;
			}
		}

		return beanToMap;

	}
	
	@SuppressWarnings("rawtypes")
	public static final SuperBean getMapToBean(Map<String , Object> beanMap , Class beanType) throws Exception {
		
		SuperBean bean = (SuperBean) Class.forName(beanType.getName()).newInstance();
		
		Iterator iter = beanMap.entrySet().iterator();
		while(iter.hasNext()) {
			Entry entry = (Entry) iter.next();
			bean.setAttributeValue(String.valueOf(entry.getKey()).toLowerCase(), entry.getValue());
		}
		
		return bean;
		
	}

	@Override
	public SuperBean clone() throws CloneNotSupportedException {
		return (SuperBean) super.clone();
	}

	// public abstract String[] getAttributeNames();
	// public abstract void setAttributeValue(String key , Object value);
	// public abstract Object getAttributeValue(String key) throws Exception ;
	// public abstract String getTableName();

}